<template>
  <!-- Modal backdrop -->
  <transition enter-active-class="transition duration-200 ease-out" enter-from-class="opacity-0"
    enter-to-class="opacity-100" leave-active-class="transition duration-100 ease-out" leave-from-class="opacity-100"
    leave-to-class="opacity-0">
    <div v-show="modalOpen" class="fixed inset-0 z-50 transition-opacity bg-gray-900/30" aria-hidden="true"></div>
  </transition>
  <!-- Modal dialog -->
  <transition enter-active-class="transition duration-200 ease-in-out" enter-from-class="translate-y-4 opacity-0"
    enter-to-class="translate-y-0 opacity-100" leave-active-class="transition duration-200 ease-in-out"
    leave-from-class="translate-y-0 opacity-100" leave-to-class="translate-y-4 opacity-0">
    <div v-show="modalOpen" :id="id"
      class="fixed inset-0 z-50 flex items-center justify-center px-4 my-4 overflow-hidden sm:px-6" role="dialog"
      aria-modal="true">
      <div ref="modalContent"
        class="w-full max-w-lg max-h-full overflow-auto bg-white rounded-lg shadow-lg dark:bg-gray-800">
        <slot />
      </div>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

const props = defineProps<{
  id?: string
  modalOpen: boolean
}>()

const emit = defineEmits<{
  (e: 'close-modal'): void
}>()

const modalContent = ref<HTMLElement | null>(null)

// close on click outside
const clickHandler = ({ target }: MouseEvent) => {
  if (!props.modalOpen || !modalContent.value?.contains(target as Node)) return
  emit('close-modal')
}

// close if the esc key is pressed
const keyHandler = ({ keyCode }: KeyboardEvent) => {
  if (!props.modalOpen || keyCode !== 27) return
  emit('close-modal')
}

onMounted(() => {
  document.addEventListener('click', clickHandler)
  document.addEventListener('keydown', keyHandler)
})

onUnmounted(() => {
  document.removeEventListener('click', clickHandler)
  document.removeEventListener('keydown', keyHandler)
})
</script>